const { DOWNLOADFILE, RENDERPROCESSCALL, SHOWDIALOG, GET_VIDEO_INFO,VIEW_DIR, SELECT_DIR,SELECT_FILES,SELECT_DIR_CALLBACK, DOWNLOAD_PATH, GET_FILE_INFO_CALLBACK, SUPPORT_IMAGE_TYPE, VIDEO_FFPEG,AUDIO_FFPEG, TERMINATE_VIDEO_CONVERSION } = require("./const/const");
const { app, ipcMain, dialog, BrowserWindow } = require('electron');
const fs = require('fs');
const os = require('os');
const path = require('path');
const url = require('url');
const fetch = require("node-fetch");
const progressStream = require('progress-stream');
const child_process = require('child_process');
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const FFmpeg = require("fluent-ffmpeg");
const sizeOf = require('image-size');
const FileType = require('file-type');
const ffprobe = require('ffprobe-static');

const setPath = isDev => {
    const ffprobePath = isDev ? ffprobe.path : path.join(process.resourcesPath, 'app.asar.unpacked', 'node_modules', 'ffprobe-static', 'bin', 'win32', 'x64', 'ffprobe.exe');
    const formateFfmpegPath = isDev ? ffmpegPath : path.join(process.resourcesPath, 'app.asar.unpacked', 'node_modules', '@ffmpeg-installer', 'win32-x64', 'ffmpeg.exe');
    FFmpeg.setFfprobePath(ffprobePath);
    FFmpeg.setFfmpegPath(formateFfmpegPath);
}

class IPC {
    win = null;
    ffmpegProcess = null;

    constructor(win) {
        const env = process.env?.NODE_ENV?.trim();
        this.mkDownloadDic(); // 创建 download 文件目录
        const isDev = env === 'development';
        setPath(isDev);
        this.win = win;
		// 获取应用的安装路径的上一级目录
		const appPath = app.getAppPath();
		const parentDir = path.dirname(appPath);
        ipcMain.on(RENDERPROCESSCALL, (event, data) => {
            console.log("get message from render process", event.processId, data);
            const { type, params } = data;
            switch (type) {
                case SHOWDIALOG:
                    this.showDialog();
                    break;
				case VIEW_DIR:
				    this.showDirDialog(params);
				    break;
				case SELECT_DIR:
				    this.selectDir(event);
				    break;
                case DOWNLOADFILE:
                    this.downloadFilesByUrl(params);
                    break;
                case GET_VIDEO_INFO:
                    this.getVideoInfo(event, params);
                    break;
                case SELECT_FILES:
                    this.selectFiles(event, params);
                    break;
            }
        });
		
		
		ipcMain.on(AUDIO_FFPEG,(event,data)=>{
			console.log('**************AUDIO_FFPEG 4')
			
			const { type, params } = data;
			
			let audioDir = path.parse(params.outpath).dir;
			if (!fs.existsSync(audioDir)) {
			    fs.mkdirSync(audioDir);
			}
			
			
			const localAudioPath = params.inputpath
			const outputAudioPath = params.outpath
			
			
			// 如果有这个文件就进行消息传递
			if (fs.existsSync(outputAudioPath)) {
			    event.sender.send('audio-converted', { outputAudioPath, audioDir });
			    return;
			}
			
			this.ffmpegProcess = FFmpeg(localAudioPath)
				.outputOptions([
					'-q:a 0',// 设置音频质量，0 为最佳质量
			        '-ar 44100', // 设置采样率为 44100 Hz
			        '-ab 192k' // 设置比特率为 192 kbps
			    ])
				// .setStartTime('00:00:00') // 从第10秒开始
				// .setDuration('00:05:10') // 持续30秒
			    .output(outputAudioPath)
			    .on('start', function (commandLine) {
			        console.log('开始转换:', commandLine);
			    })
			    .on('progress', function (progress) {
			        console.log('转换进度:', progress.percent + '%');
			        event.sender.send('audio-progress', progress.percent);
			    })
			    .on('end', function () {
			        console.log('转换完成', outputAudioPath);
			        // 传给渲染进程播放视频
			        event.sender.send('audio-converted', { outputAudioPath, audioDir,params });
			        // fs.unlinkSync(localAudioPath);
			    })
			    .on('error', function (err) {
			        console.error('转换出错:', err.message);
			         if(err.message == 'ffmpeg was killed with signal SIGINT'){
			            // 删除文件
			            // fs.unlinkSync(localAudioPath);
			            fs.unlinkSync(outputAudioPath);
			         }
			    });
			this.ffmpegProcess.run();
		});
		
        // 监听来自渲染进程的转码请求
        ipcMain.on(VIDEO_FFPEG, (event, inputPath) => {
            // 网络视频链接
            const hevcVideoUrl = inputPath;
            let yfvideoDir;
            if (isDev) {
                yfvideoDir = path.join(__dirname, 'yfvideo'); // 开发环境使用相对路径
            } else {
                yfvideoDir = path.join(parentDir, 'yfvideo'); // 生产环境使用 app.getPath
            }
            if (!fs.existsSync(yfvideoDir)) {
                fs.mkdirSync(yfvideoDir);
            }
            // 本地临时保存路径
            const localVideoPath = path.join(yfvideoDir, `hevc${url.parse(inputPath).pathname.split('/').pop()}`);
            // 解码后的视频文件路径
            const outputVideoPath = path.join(yfvideoDir, url.parse(inputPath).pathname.split('/').pop());
            // 如果有这个文件就进行消息传递
            if (fs.existsSync(outputVideoPath)) {
                event.sender.send('video-converted', { outputVideoPath, yfvideoDir });
                return;
            }
            // 判断格式
            FFmpeg.ffprobe(inputPath, (err, data) => {
                if (err) {
                    event.sender.send('video-converted', { outputVideoPath: err, yfvideoDir });
                    return;
                }

                const videoStream = data.streams.find(stream => stream.codec_type === 'video');
                if (videoStream) {
                    const codecName = videoStream.codec_name;
                    console.log('Video codec:', codecName);
                    if (codecName === 'hevc') {
                        console.log('The video is in HEVC format.');
                        // 下载视频到本地
                        fetch(hevcVideoUrl)
                            .then(response => {
                                if (!response.ok) {
                                    throw new Error(`HTTP error! status: ${response.status}`);
                                }
                                const fileStream = fs.createWriteStream(localVideoPath);
                                response.body.pipe(fileStream);

                                return new Promise((resolve, reject) => {
                                    fileStream.on('finish', resolve);
                                    fileStream.on('error', reject);
                                });
                            })
                            .then(() => {
                                console.log('视频下载完成');
                                // 下载完成后使用 fluent-ffmpeg 进行解码
                                this.ffmpegProcess = FFmpeg(localVideoPath)
                                    .output(outputVideoPath)
                                    .videoCodec('libx264')
                                    .audioCodec('aac')
                                    .on('start', function (commandLine) {
                                        console.log('开始解码:', commandLine);
                                    })
                                    .on('progress', function (progress) {
                                        console.log('解码进度:', progress.percent + '%');
                                        event.sender.send('video-progress', progress.percent);
                                    })
                                    .on('end', function () {
                                        console.log('解码完成', outputVideoPath);
                                        // 传给渲染进程播放视频
                                        event.sender.send('video-converted', { outputVideoPath, yfvideoDir });
                                        fs.unlinkSync(localVideoPath);
                                    })
                                    .on('error', function (err) {
                                        console.error('解码出错:', err.message);
                                         if(err.message == 'ffmpeg was killed with signal SIGINT'){
                                            // 删除文件
                                            fs.unlinkSync(localVideoPath);
                                            fs.unlinkSync(outputVideoPath);
                                         }
                                    });
                                this.ffmpegProcess.run();
                            })
                            .catch(error => {
                                console.error('视频下载失败:', error.message);
                            });
                    } else {
                        console.log('The video is not in HEVC format.', codecName);
                        event.sender.send('video-converted', { outputVideoPath: inputPath, yfvideoDir:outputVideoPath });
                    }
                } else {
                    console.error('No video stream found.');
                }
            });
        });

        // 监听终止视频解析请求
        ipcMain.on(TERMINATE_VIDEO_CONVERSION, (event) => {
            if (this.ffmpegProcess) {
                this.ffmpegProcess.kill('SIGINT', (err) => {
                   
                });
            } else {
                console.log('没有正在运行的解码进程');
            }
        });
    }

    showDialog() {
        child_process.exec(`start "" ${path.resolve(os.homedir(), 'Download/')}`);
    }
	showDirDialog(filepath) {
		console.log(filepath)
	    child_process.exec(`start "" ${path.parse(filepath).dir}`);
	}
	

    mkdirsSync(dirname) {
        if (fs.existsSync(dirname)) {
            return true;
        } else {
            if (this.mkdirsSync(path.dirname(dirname))) {
                fs.mkdirSync(dirname);
                return true;
            }
        }
    }

    mkDownloadDic() {
        const downloadDicPath = path.resolve(os.homedir(), 'Download/');
        this.mkdirsSync(downloadDicPath);
    }
    downloadFilesByUrl(file_url) {
        try {
            const cwd = process.resourcesPath;
            const downloadDicPath = path.resolve(os.homedir(), 'Download/');
            if (!fs.existsSync(downloadDicPath)) {
                fs.mkdirSync(downloadDicPath);
            }
            const file_name = url.parse(file_url).pathname.split('/').pop();
            const file_path = path.resolve(downloadDicPath, file_name);
            const file_path_temp = `${file_path}.tmp`;
            if (!fs.existsSync(file_path)) {
                // 创建写入流
                const fileStream = fs.createWriteStream(file_path_temp)
                    .on('error', function (e) {
                        console.error('error==>', e);
                    })
                    .on('ready', function () {
                        console.log("开始下载:", file_url);
                    })
                    .on('finish', function () {
                        try {
                            // 下载完成后重命名文件
                            fs.renameSync(file_path_temp, file_path);
                            console.log('文件下载完成:', file_path);
                        } catch (err) {
                            console.error('重命名文件失败:', err);
                        }
                    });
                // 请求文件
                fetch(file_url, {
                    method: 'GET',
                    headers: { 'Content-Type': 'application/octet-stream' },
                }).then(res => {
                    // 获取请求头中的文件大小数据
                    let fsize = res.headers.get("content-length");
                    // 创建进度
                    let str = progressStream({
                        length: fsize,
                        time: 100 /* ms */
                    });
                    // 下载进度 
                    str.on('progress', function (progressData) {
                        // 不换行输出
                        let percentage = Math.round(progressData.percentage) + '%';
                        console.log(percentage);
                    });
                    res.body.pipe(str).pipe(fileStream);
                }).catch(e => {
                    // 自定义异常处理
                    console.log(e);
                });
            } else {
                // 已存在
                console.log(path.resolve(downloadDicPath, file_name), '已存在，不下载');
            }
        } catch (err) {
            console.log('下载文件失败，请稍后重试。', err);
        }
    }
    async _getVideoInfo(event, filePath) {
        let videoDuration, videoSize;
        const screenshotName = path.basename(filePath).split('.').shift() + '.png';
        const screenshotPath = path.resolve(DOWNLOAD_PATH, screenshotName);
        const { ext } = await FileType.fromFile(filePath);
        return new Promise((resolve, reject) => {
            try {
                FFmpeg(filePath)
                    .on('end', async (err, info) => {
                        const { width, height, type, size } = await this._getImageInfo(screenshotPath);
                        resolve({
                            videoDuration,
                            videoPath: filePath,
                            videoSize,
                            videoType: ext,
                            screenshotPath,
                            screenshotWidth: width,
                            screenshotHeight: height,
                            screenshotType: type,
                            screenshotSize: size,
                        });
                    })
                    .on('error', (err, info) => {
                        event.reply('main-process-error', err);
                        reject(err);
                    })
                    .screenshots({
                        timestamps: [0],
                        filename: screenshotName,
                        folder: DOWNLOAD_PATH
                    }).ffprobe((err, metadata) => {
                        if (!err) {
                            videoDuration = metadata.format.duration;
                            videoSize = metadata.format.size;
                        } else {
                            event.reply('main-process-error', err);
                            console.log(err);
                        }
                    });
            } catch (err) {
                event.reply('main-process-error', err);
                console.log(err);
            }
        });
    }

    async _getImageInfo(path) {
        const { width, height, type } = await sizeOf(path);
        const { size } = fs.statSync(path);
        return {
            width, height, type, size
        };
    }
    async getVideoInfo(event, params) {
        const { path } = params;
        const data = await this._getVideoInfo(event, path);
        event.reply(GET_FILE_INFO_CALLBACK, { triggerType: GET_VIDEO_INFO, data });
    }
	
	async selectDir(event) {		
		const { canceled, filePaths } = await dialog.showOpenDialog(this.win,
			{properties: ['openDirectory']}	
		)
	
		const data = {
			dir:filePaths[0] ? filePaths[0] + "\\" : ''
		}
		console.log(data)
		
	    event.reply(SELECT_DIR_CALLBACK, { triggerType: SELECT_DIR, data });
	}

    async selectFiles(event, params) {
        const { extensions, fileType, multiSelections } = params;
        const filePaths = dialog.showOpenDialogSync(this.win, {
            properties: ['openFile', 'multiSelections'],
            filters: [{
                name: "Images", extensions: extensions
            }],
        });        
        if (filePaths) {
            filePaths.forEach(async filePath => {
                const size = fs.statSync(filePath).size;
                const name = path.parse(filePath).base;
                const type = name.split('.')[1];

                const data = {
                    path: filePath,
                    size,
                    name,
                    type
                };

                if (SUPPORT_IMAGE_TYPE.find(v => type.includes(v))) {
                    const fileContent = await fs.readFileSync(filePath);
                    data.fileContent = fileContent;
                }

                event.reply(GET_FILE_INFO_CALLBACK, {
                    triggerType: SELECT_FILES,
                    data
                });
            });
        }
    }
}

module.exports = IPC;